import axios from 'axios'
// @ts-ignore
import qs from 'qs'
import {ElMessage} from 'element-plus'
import store from '@/stores'
import cache from '@/utils/cache'
import {getUserToken} from "@/utils/auth";


// 是否正在刷新的标记
let isRefreshing = false;
//重试队列，每一项将是一个待执行的函数形式
let requests: any = [];


/**
 * 重试请求
 * @param config
 * @returns {Promise<unknown>|Promise<boolean>}
 */
function retryTokenReqest(config: any) {
    console.log('--未授权或令牌过期，系统自动刷新令牌，重新请求--')
    //config.baseURL = '';
    if (!isRefreshing) {
        isRefreshing = true
        return getUserToken().then((res) => {
            if (config.headers) {
                config.headers['Authorization'] = "Bearer " + res
            }
            // 已经刷新了token，将所有队列中的请求进行重试
            requests.forEach(cb => cb(res));
            requests = [];

            return service(config);
        }).catch((e) => {
            console.error('refreshtoken error =>', e)
            return Promise.reject()
        }).finally(() => {
            isRefreshing = false
        });

    } else {
        // 正在刷新token，将返回一个未执行resolve的promise
        return new Promise((resolve) => {
            // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
            requests.push((token: any) => {
                if (config.headers) {
                    config.headers['Authorization'] = "Bearer " + token;
                }
                resolve(service(config))
            })
        })
    }
}

// axios实例
// @ts-ignore
const service = axios.create({
    baseURL: window.apiGateway + window.apiAdmin,
    headers: {'Content-Type': 'application/json;charset=UTF-8'},
    withCredentials: true
})

// 请求拦截器
service.interceptors.request.use(
    (config: any) => {
        const userStore = store.userStore
        if (userStore?.token) {
            config.headers.Authorization = 'Bearer ' + userStore.token
        }
        config.headers['Accept-Language'] = cache.getLanguage()
        // 追加时间戳，防止GET请求缓存
        if (config.method?.toUpperCase() === 'GET') {
            config.params = {...config.params, t: new Date().getTime()}
        }
        if (Object.values(config.headers).includes('application/x-www-form-urlencoded')) {
            config.data = qs.stringify(config.data)
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

// 响应拦截器
service.interceptors.response.use(
    response => {
        const res = response.data
        const config = response.config
        if (res.status == 200 && res.msg == 'refreshToken') {
            // 令牌到期后，刷新新的令牌 拿到token后，重新请求一下
            console.log('--令牌过期，系统自动刷新令牌，重新请求--')
            store.userStore.setToken(res.data.data);
            // @ts-ignore
            config.headers['Authorization'] = "Bearer " + res.data
            return service(config);
        } else if (res.status == '401') {
            // 未授权或token过期，需要重新获取token，拿到令牌后需要重新请求一下
            return retryTokenReqest(config);
        }
        return res
    },
    error => {
        if (error.response && error.response.status) {
            // 对应的状态码描述可能与具体场景不一样，可能需要自行确认和修改
            switch (error.response.status) {
                case 400:
                    ElMessage.error('请求错误（code 400）')
                    break
                case 401:
                    // eslint-disable-next-line no-case-declarations
                    const config = error.response.config;
                    return retryTokenReqest(config);
                case 403:
                    ElMessage.error('拒绝访问（code 403）')
                    break
                case 404:
                    ElMessage.error(`请求地址出错：${error.response.config.url}（code 404）`)
                    break
                case 408:
                    ElMessage.error('请求超时 (code 408)')
                    break
                case 500:
                case 900:
                    // eslint-disable-next-line no-case-declarations
                    let msg = "系统异常，请联系管理员。 (code 500)"
                    if (error.response.data && error.response.data.message) {
                        msg = error.response.data.message
                    }
                    ElMessage.error(msg)
                    break
                case 501:
                    ElMessage.error('系统异常，请联系管理员。 (code 501)')
                    break

                case 502:
                    ElMessage.error('系统异常，请联系管理员。 (code 502)')
                    break

                case 503:
                    ElMessage.error('服务不可用 (code 503)')
                    break

                case 504:
                    ElMessage.error('系统异常，请联系管理员 (code 504)')
                    break

                case 505:
                    ElMessage.error('HTTP版本不受支持 (code 505)')
                    break
                case 703:
                    ElMessage.error('token过期，请重新登录')
            }
        }
        return Promise.reject(error)
    }
)

// 导出 axios 实例
export default service
